import dayjs from "dayjs";
import "dayjs/locale/zh-cn";
dayjs.locale("zh-cn");

// 相对时间
import relativeTime from "dayjs/plugin/relativeTime";
// 持续时间
import duration from "dayjs/plugin/duration";
// 时间之间
import isBetween from "dayjs/plugin/isBetween";
// 相同或之后
import isSameOrAfter from "dayjs/plugin/isSameOrAfter";
// 相同或之前
import isSameOrBefore from "dayjs/plugin/isSameOrBefore";
// 是否今天
import isToday from "dayjs/plugin/isToday";


dayjs.extend(isBetween);
dayjs.extend(isSameOrAfter);
dayjs.extend(isSameOrBefore);
dayjs.extend(isToday);
dayjs.extend(duration);
dayjs.extend(relativeTime);

// dayjs类型判断
type UnitTypeShort = "d" | "M" | "y" | "h" | "m" | "s" | "ms";
type UnitType =
  | "millisecond"
  | "second"
  | "minute"
  | "hour"
  | "day"
  | "month"
  | "year"
  | "date"
  | UnitTypeShort;

type OpUnitType = UnitType | "week" | "w";

/**
 * 获取季度时间
 *
 * @returns
 */
export function uarterOfYearDateRange() {
  const startTime = formateDate(
    dayjs(formateDate())
      .quarter(dayjs(formateDate()).quarter() - 1)
      .startOf("month")
      .subtract(2, "month")
  );
  const endTime = formateDate(
    dayjs(formateDate())
      .quarter(dayjs(formateDate()).quarter() - 1)
      .endOf("month")
  );
  return {
    startTime,
    endTime
  };
}

/**
 * 时间戳转换
 *
 * @param params
 * @returns
 */
export function formateMill(date?: string | number) {
  return dayjs(date).valueOf();
}

// 格式化时间数据
/**
 *
 * @param date 有参数时根据传入时间格式化, 没有就默认当前时间
 * @param hasHours 是否需要格式化成 年-月-日 时:分:秒 不传返回年-月-日
 */
export function formateDate(date?: any, hasHours = false) {
  return dayjs(date || new Date()).format(`YYYY-MM-DD${hasHours ? " HH:mm:ss" : ""}`);
}

export function formateYearDate(date?: any, hasHours = false) {
  return dayjs(date || new Date()).format(`YYYY年MM月DD日${hasHours ? " HH:mm:ss" : ""}`);
}

/**
 * 判断时间相同或之后
 *
 * @param {Date} dateTime
 * @param {Date} contrastDateTime
 * @param {String} dateType
 * @returns
 */
export function isNowDateSameOrAfter(dateTime: string, contrastDateTime: string, dateType = "day") {
  return dayjs(dateTime).isSameOrAfter(contrastDateTime, dateType);
}

/**
 * 判断时间相同或之前
 *
 * @param {Date} dateTime
 * @param {Date} contrastDateTime
 * @param {String} dateType
 * @returns
 */
export function isNowDateSameOrBefore(
  dateTime: string,
  contrastDateTime: string,
  dateType = "day"
) {
  return dayjs(formateDate(dateTime)).isSameOrBefore(contrastDateTime, dateType);
}

/**
 * 判断当前时间是否今天
 *
 * @param {Date} dateTime
 * @returns
 */
export function isNowDateTime(dateTime: string, nowDate = formateDate(new Date())) {
  return dayjs(dateTime).isToday(nowDate);
}

/**
 * 判断当前时间是否包含在内
 *
 * @param {Date} nowDate
 * @param {Date} beforeDate
 * @param {Date} afterDate
 * @returns Boolean
 */
export function isBetweenDateTime(nowDate: string, beforeDate: string, afterDate: string) {
  return dayjs(nowDate).isBetween(beforeDate, dayjs(afterDate));
}

/**
 * 增加一定时间
 *
 * @param dateType 时间类型
 * @param num 需要调整的时间数量
 */
export function formateAddDate(dateType: OpUnitType, num: number, date?: string) {
  return formateDate(dayjs(date || new Date()).add(num, dateType));
}

/**
 * 减去一定时间
 *
 * @param dateType 时间类型
 * @param num 需要调整的时间数量
 */
export function formateSubtractDate(dateType: OpUnitType, num: number, date?: string) {
  return formateDate(dayjs(date || new Date()).subtract(num, dateType));
}

/**
 * 日期相减
 *
 * @param target  作为目标日期
 * @param calcDate  提供为计算的日期
 * @returns 天数
 */
export function getDaysBetween(target: string, calcDate: string): number {
  const startDate = Date.parse(calcDate);
  const endDate = Date.parse(target);

  if (startDate > endDate) {
    return 0;
  }
  if (startDate == endDate) {
    return 1;
  }
  const days = Math.ceil((endDate - startDate) / (1 * 24 * 60 * 60 * 1000));
  return isNaN(days) ? 0 : days;
}

/**
 *初始化时间 开始时间
 *
 * @param dateType 时间类型
 * @param date YYYY-MM-DD字符串时间格式
 */
export function formatterStartDate(dateType: OpUnitType, date?: string | number): string {
  return formateDate(dayjs(date || new Date()).startOf(dateType));
}

/**
 *初始化时间的末尾
 *
 * @param dateType 时间类型
 * @param date YYYY-MM-DD字符串时间格式
 */
export function formatterEndDate(dateType: OpUnitType, date?: string | number): string {
  return formateDate(dayjs(date || new Date()).endOf(dateType));
}

/**
 * 判断是否在某个时间范围内，包含当日
 *
 * @param startDate 开始时间
 * @param endDate 结束时间
 * @param date 对比时间
 * @returns
 */
export function isRangeDateTime(startDate: string, endDate: string, date: string): boolean {
  // 是否在之前
  const isBefore = isNowDateSameOrBefore(startDate, date);
  // 是否在之后
  const isAfter = isNowDateSameOrAfter(endDate, date);
  if (isBefore && isAfter) {
    return true;
  }
  return false;
}

/**
 * 获取月份时间
 *
 * @param date YYYY-MM-DD字符串时间格式
 * @returns 月份里的日期
 */
export function getMonthDate(date?: string): number {
  return dayjs(date || new Date()).get("date");
}

/**
 * 获取星期数
 *
 * @param date YYYY-MM-DD字符串时间格式
 * @returns 星期几 (星期天0，星期六6)
 */
export function getWeekenDate(date?: string): number {
  return dayjs(date || new Date()).get("day");
}

/**
 * 格式化小于10的天数据
 *
 * @param day 0 ~ 31 天数据
 */
export function formatDay(day: number) {
  if (day <= 9) {
    return `0${day}`;
  } else {
    return `${day}`;
  }
}

/**
 * 截取年月日时间格式的年月
 *
 * @param monthDate YYYY-MM-DD时间格式的字符串
 * @return YYYY-MM
 */
export function cutOutYearMonthHasLink(monthDate: string) {
  if (!monthDate) return ""
  return monthDate
    .split("-")
    .slice(0, 2)
    .join("-");
}
/**
 * 截取年月日时间格式的年
 *
 * @param monthDate YYYY-MM-DD时间格式的字符串
 * @return MM-DD
 */
export function cutOutYearHasLink(monthDate: string) {
  if (!monthDate) return ""
  return monthDate
    .split("-")
    .slice(1)
    .join("-");
}

/**
 * 截取年月日时间格式的年月
 *
 * @param monthDate YYYY-MM-DD时间格式的字符串
 * @return YYYYDD
 */
export function cutOutYearMonthNotLink(monthDate: string) {
  if (!monthDate) return ""
  return monthDate
    .split("-")
    .slice(0, 2)
    .join("");
}

/**
 * 截取年月日时间格式的日
 *
 * @param monthDate YYYY-MM-DD时间格式的字符串
 * @return 01 ~ 31
 */
export function cutOutYearDay(monthDate: string) {
  if (!monthDate) return ""
  return monthDate
    .split("-")
    .slice(-1)
    .join("");
}

/**
 * 去掉年月日时分秒的秒
 *
 * @param monthDate YYYY-MM-DD HH:mm:ss时间格式的字符串
 * @return YYYY-MM-DD HH:mm
 */
export function cutOutOfSeconds(monthDate: string) {
  if (!monthDate) return ""
  return monthDate.slice(0, -3);
}
/**
 * 保留月和日
 *
 * @param monthDate YYYY-MM-DD HH:mm:ss时间格式的字符串
 * @return MM-DD
 */
export function cutSaveOfMonthAndDay(monthDate: string) {
  if (!monthDate) return ""
  return monthDate.slice(5, 10);
}

/**
 * 根据时间截取时分
 *
 * @param dateTime YYYY-MM-DD HH:mm:ss
 * @returns HH:mm
 */
export function useSliceDateTime(dateTime: string, sec = false): string {
  const time = formateDate(dateTime, true);
  return !sec ? time.slice(11, 16) : time.slice(11);
}

/**
 * 相对时间计算
 *
 * @param comparisonTime 对比时间
 * @param targetTime 目标时间
 * @returns
 */
export function useRelativeTime(comparisonTime?: string, targetTime?: string) {
  return dayjs(formateDate(targetTime, true)).from(formateDate(comparisonTime, true), true);
}

/**
 * 获取星期数
 *
 * @param date YYYY-MM-DD字符串时间格式
 * @returns 星期几 (星期天0，星期六6)
 */
export function getWeekDate(date = new Date()) {
  return dayjs(date || new Date()).get("day");
}

/**
 * 获取每周日期范围
 *
 * @param {Date} date
 * @returns 周一 ~ 周日格式的 YYYY-MM-DD
 */
export function useWeekRange(date = new Date()) {
  // 周一 ~ 周六: 1 ~ 6; 周日: 0
  const day = getWeekDate(date);
  let startTime = "";
  let endTime = "";
  startTime = formateSubtractDate("day", day ? day - 1 : 6 - day, formateDate(date));
  endTime = formateAddDate("day", day ? 7 - day : day, formateDate(date));
  return {
    startTime,
    endTime
  };
}

/**
 * 获取上周日期范围
 *
 * @returns 上周一 ~ 上周日 YYYY-MM-DD
 *
 */
export function usePreWeekRange(date = new Date()) {
  const day = getWeekDate(date);
  let startTime = "";
  let endTime = "";
  // startTime = formateSubtractDate("day", day ? (day - 1): (6 - day), formateDate(date));
  startTime = formateSubtractDate(
    "day",
    7,
    formateSubtractDate("day", day ? day - 1 : 6 - day, formateDate(date))
  );
  endTime = formateSubtractDate(
    "day",
    7,
    formateAddDate("day", day ? 7 - day : day, formateDate(date))
  );
  return {
    startTime,
    endTime
  };
}

/**
 * 获取上月日期范围
 *
 * @returns 上月月初~月末 YYYY-MM--DD
 */
export function usePreMonthRange() {
  const startTime = formatterStartDate("month", formateSubtractDate("month", 1, formateDate()));
  const endTime = formatterEndDate("month", formateSubtractDate("month", 1, formateDate()));
  return {
    startTime,
    endTime
  };
}